﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace ITAP.ContourBuilder.Manipulation
{   
    public abstract class ContourAction : IExecutable, ICommand
    {
        protected List<ICommand> commandsToExecute;
        protected string name;
        protected ContourControl control;

        public ContourControl Control
        {
            get { return control; }
            set { control = value; }
        }

        public ContourAction(string name)
        {
            this.name = name;
            commandsToExecute = new List<ICommand>();
        }

        public virtual void Execute()
        {
            foreach (ICommand command in this.commandsToExecute)
                command.Execute();
        }

        public virtual void Exit()
        {
            foreach (ICommand command in commandsToExecute)
                command.Terminate();
        }

        public override string ToString()
        {
            return name;
        }

        public virtual Bitmap Icon
        {
            get { return null; }
        }

        #region ICommand Members

        public virtual CommandState State
        {
            get 
            {
                foreach (ICommand command in this.commandsToExecute)
                    if (command.State == CommandState.Execute)
                        return CommandState.Execute;

                // TODO: Пока что это убрал, т.к. не определился с тем, что должен возвращать Action в этом случае.

                //bool allEndExecuted = true;
                //foreach (ICommand command in this.commandsToExecute)
                //    if (command.State != CommandState.EndExecute)
                //        allEndExecuted = false;

                //if (allEndExecuted)
                //    return CommandState.EndExecute;

                //bool allNotExecuted = true;
                //foreach (ICommand command in this.commandsToExecute)
                //    if (command.State != CommandState.NotExecute)
                //        allNotExecuted = false;

                //if (allNotExecuted)
                //    return CommandState.NotExecute;

                return CommandState.NotExecute; 
            }
        }

        public virtual event ManipulatorEvent StateChanged;

        public virtual void Undo()
        {
            // TODO: ???
            foreach (ICommand command in commandsToExecute)
                command.Undo();
        }

        public virtual void Redo()
        {
            // TODO: ???
            foreach (ICommand command in commandsToExecute)
                command.Redo();
        }

        public string Name
        {
            get { return name; }
        }

        public virtual bool CanUndo
        {
            get 
            {
                return false;
            }
        }

        private bool enabled = true;
        public bool Enabled
        {
            get
            {
                return enabled;
            }
            set
            {
                enabled = value;
            }
        }

        public void ObtainPeripheryState(GlobalPeripheryState state)
        {            
            foreach (ICommand command in commandsToExecute)
            {
                if (command.DisableObtainPeripheryState || command.State != CommandState.Execute)
                    continue;

                command.ObtainPeripheryState(state);
                //ObtainPeripheryStateDelegate dlg = new ObtainPeripheryStateDelegate(command.ObtainPeripheryState);
                //dlg.BeginInvoke(state, null, null);
            }

        }

        protected bool disableObtainPeripheryState = false;
        public bool DisableObtainPeripheryState
        {
            get
            {
                return disableObtainPeripheryState;
            }
            set
            {
                disableObtainPeripheryState = value;
            }
        }

        public virtual void DrawOnGraphics(Graphics g, int screenWidth, int screenHeight, RectangleF modelRectangle, ITAP.Core.Modelling.ModelPoint cameraCenter, ITAP.Core.Calculations.ModelCoordinateConverter coordinateConverter)
        {
            foreach (ICommand command in commandsToExecute)
                command.DrawOnGraphics(g, screenWidth, screenHeight, modelRectangle, cameraCenter, coordinateConverter);
        }

        public virtual bool AllowMultipleInstances
        {
            get { throw new NotImplementedException(); }
        }

        public virtual void SaveToHistory()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ICloneable Members

        public virtual object Clone()
        {
            ContourAction clone = (ContourAction)Activator.CreateInstance(this.GetType(), new object[] { this.name });
            foreach (ICommand command in this.commandsToExecute)
                clone.commandsToExecute.Add(command.Clone() as ICommand);

            clone.control = this.control;
            return clone;
        }

        #endregion

        #region ICommand Members


        public void Terminate()
        {
            foreach (ICommand command in this.commandsToExecute)
                command.Terminate();
        }

        #endregion

        #region IExecutable Members


        public void Cancel()
        {
            foreach (ICommand command in this.commandsToExecute)
                command.Cancel();
        }

        #endregion
    }
}
